using System;
using System.Diagnostics;

using org.fourzoas.noise.module;

namespace org.fourzoas.noise.module {
  /// <summary>
  /// A callback function used by the <see cref="MathFunction"/> noise module.
  /// </summary>
  /// <param name="x">The <em>x</em> coordinate of a point.</param>
  /// <param name="y">The <em>y</em> coordinate of a point.</param>
  /// <param name="z">The <em>z</em> coordinate of a point.</param>
  /// <returns>The value at the given point.</returns>
  /// <remarks>
  /// The callback function should return a value [-1, 1] based upon the point (<paramref name="x"/>, 
  /// <paramref name="y"/>, <paramref name="z"/>).
  /// </remarks>
  /// <example>See <see cref="MathFunction"/>.</example>
  public delegate double MathFunctionCallback(double x, double y, double z);
  /// <summary>
  /// A <see cref="GeneratorModule"/> that generates its value based upon a function.
  /// </summary>
  /// <remarks>
  /// By default, <see cref="GetValue"/> will return 0.0 regardless of the input values.  Use the <see cref="Callback"/>
  /// property to assign a generating function to this module.
  /// </remarks>
  /// <example>
  /// Creates a <see cref="MathFunction"/> module, and assigns it a function that returns a value based upon the distance from 
  /// the origin.
  /// <code>
  ///   MathFunction mod = new MathFunction();
  ///   mod.Callback = delegate(double x, double y, double z) {
  ///     double d = x * x + y * y + z * z;
  ///     if (d &lt; 1.0)
  ///       return 1.0;
  ///     return 2.0 / d - 1.0;
  ///   }
  ///   double value = mod.GetValue(1, 2, 3);
  /// </code>
  /// <c>value</c> will have a value of -0.857143.
  /// </example>
  public class MathFunction : GeneratorModule {
    /// <summary>
    /// Default constructor.
    /// </summary>
    public MathFunction()
      : base(1) {
      m_callback = delegate(double x, double y, double z) { return 0; };
    }
    /// <summary>
    /// Generates an output value given the coordinates of the specified input value.
    /// </summary>
    /// <param name="x">The <em>x</em> coordinate of the input value.</param>
    /// <param name="y">The <em>y</em> coordinate of the input value.</param>
    /// <param name="z">The <em>z</em> coordinate of the input value.</param>
    /// <returns>The output value.</returns>
    public override double GetValue(double x, double y, double z) {
      return m_callback(x, y, z);
    }
    /// <summary>
    /// Returns the number of source modules required by this noise module.
    /// </summary>
    /// <returns>The number of source modules required by this noise module.</returns>
    public override int GetSourceModuleCount() {
      return 0;
    }
    /// <summary>
    /// The callback function
    /// </summary>
    private MathFunctionCallback m_callback;
    /// <summary>
    /// Gets or sets the callback function
    /// </summary>
    public MathFunctionCallback Callback {
      get { return m_callback; }
      set { m_callback = value; }
    }

  }
}
